package com.ruoyi.system.outto.utils;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.exception.GlobalException;
import com.ruoyi.common.utils.ImgUntil;
import com.ruoyi.common.utils.ImgUntilYS;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.V2.gameAttr.mapper.GameAttrTemplateMapper;
import com.ruoyi.system.model.domain.GameAttrTemplate;
import com.ruoyi.system.model.dto.GoodsInfoAndAttrValueDto;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.*;

@Component
public class GoodsInfoUtils {
    @Autowired
    private GameAttrTemplateMapper gameAttrTemplateMapper;

    /**
     * 获取商品信息图片信息，以 String 类型展示
     */
    public String getGoodsInfoImageString(GoodsInfoAndAttrValueDto goodsInfoAndAttrValueDto) {
        return getGoodsInfoAllImage(goodsInfoAndAttrValueDto, true);
    }

    /**
     * 获取商品信息图片信息，以 List 类型展示
     */
    public List<String> getGoodsInfoImageList(GoodsInfoAndAttrValueDto goodsInfoAndAttrValueDto) {
        String imgUrls = getGoodsInfoAllImage(goodsInfoAndAttrValueDto, true);
        return Arrays.asList(imgUrls.split(","));
    }

    /**
     * 获取商品信息图片信息
     *
     * @param needTitleImg 是否需要主图（默认添加主图）
     */
    public String getGoodsInfoAllImage(GoodsInfoAndAttrValueDto goodsInfoAndAttrValueDto, boolean needTitleImg) {

        List<Map<String, Object>> urlArr = goodsInfoAndAttrValueDto.getUrlArr();
        StringBuffer goodsImgStr = new StringBuffer();
        if (needTitleImg) {
            if (StringUtils.isNotEmpty(goodsInfoAndAttrValueDto.getTitleImg())) {
                goodsImgStr.append(",").append(goodsInfoAndAttrValueDto.getTitleImg());
            }
        }
        if (ObjectUtil.isNotEmpty(urlArr)) {
            for (Map<String, Object> maps : urlArr) {
                String ss = String.valueOf(maps.get("url"));
                goodsImgStr.append(",").append(ss);
            }
        }
        String imgUrls = goodsImgStr.toString().substring(1);
        if (StringUtils.isEmpty(imgUrls))
            throw new GlobalException("商品不存在任何图片");

        return imgUrls;
    }

    //==========================================================区服匹配==========================================================//

    /**
     * 匹配商品区服信息
     *
     * @param goodsInfoAndAttrValueDto 商品信息
     * @param interAttrServer          需要匹配的所有区服信息
     * @return 匹配到的区服
     */
    public JSONObject matchGoodsServer(GoodsInfoAndAttrValueDto goodsInfoAndAttrValueDto, String interAttrServer) {
        if (ObjectUtil.isEmpty(goodsInfoAndAttrValueDto) || ObjectUtil.isEmpty(interAttrServer))
            throw new GlobalException("区服匹配参数错误");

        String gameType = goodsInfoAndAttrValueDto.getGameType();
        // 存放商品的所有区服 id
        List<String> goodsServerIdList = new ArrayList<>();
        // 0 手游 手游必端游多两级 系统以及运营商
        if (gameType.equals("0")) {
            goodsServerIdList.add(goodsInfoAndAttrValueDto.getSystemId().toString());
            goodsServerIdList.add(goodsInfoAndAttrValueDto.getCarrierId().toString());
        }
        goodsServerIdList.add(goodsInfoAndAttrValueDto.getGroupId().toString());
        goodsServerIdList.add(goodsInfoAndAttrValueDto.getServerId().toString());

        // 转换区服类型
        JSONObject serverJsonObject = JSONObject.parseObject(interAttrServer);
        //开始匹配一级区服
        String interServeReqs = serverJsonObject.getString("interServeReqs");
        List<JSONObject> serversDataList = JSONObject.parseArray(interServeReqs, JSONObject.class);
        // 遍历区服匹配信息
        List<JSONObject> handleServersDataList = new ArrayList<>();
        for (JSONObject serversData : serversDataList) {
            // 遍历区服列表
            recursionServersDataList(null, serversData, goodsServerIdList, handleServersDataList);
        }
        // 定义一个最大匹配数量
        int matchMaxCount = 0;
        // 定义空 json 用于承接匹配到的区服信息
        JSONObject matchServerData = new JSONObject();
        // 遍历处理之后的区服列表
        for (JSONObject handleServerData : handleServersDataList) {
            // 获取区服列表完整的区服 id
            LinkedHashSet<String> allServerIdList = (LinkedHashSet<String>) handleServerData.get("allServerId");
            // 计算商品区服列表与匹配的区服列表两个列表匹配的个数，匹配最多的则代表是所需的区服信息
            int matchCount = listMatchCount(goodsServerIdList, allServerIdList);
            if (matchCount > matchMaxCount) {
                // 赋值
                matchServerData = handleServerData;
                matchMaxCount = matchCount;
            } else if (matchCount == matchMaxCount) {// 两者相等则判断匹配位置
                // 获取两者的匹配深度
                int matchServerIndex = checkMatchServerDataDeep(goodsServerIdList, matchServerData);
                int handleServerIndex = checkMatchServerDataDeep(goodsServerIdList, handleServerData);

                // 前者大于后者说明前者匹配的位置更深：例如后者匹配到了 carrier_id，而前者匹配到了 group_id
                if (handleServerIndex > matchServerIndex) {
                    matchServerData = handleServerData;
                }
            }
        }
        // 返回匹配到的区服信息
        return matchServerData;
    }

    /**
     * 验证匹配区服数据的深度
     *
     * @param goodsServerIdList 商品区服信息列表
     * @param serverData        处理的区服数据
     * @return 匹配深度，值越大，代表匹配越深，也就越精确
     */
    private int checkMatchServerDataDeep(List<String> goodsServerIdList, JSONObject serverData) {
        String[] serverDataServerIds = ((LinkedHashSet<String>) serverData.get("allServerId")).toArray(new String[0]);
        for (int i = goodsServerIdList.size() - 1; i >= 0; i--) {
            for (int y = serverDataServerIds.length - 1; y >= 0; y--) {
                if (goodsServerIdList.get(i).contains(serverDataServerIds[y])) {
                    return i;
                }
            }
        }
        return 0;
    }

    /**
     * 遍历区服列表，并获取
     *
     * @param parentServerData      匹配数据的父级数据
     * @param serverData            需要匹配的数据
     * @param goodsServerIdList     商品的区服 id 列表
     * @param handleServersDataList 处理之后的区服信息列表
     */
    private void recursionServersDataList(JSONObject parentServerData, JSONObject serverData, List<String> goodsServerIdList, List<JSONObject> handleServersDataList) {
        // 下级区服
        JSONArray secondInterServerRes = serverData.getJSONArray("interServerRes");
        if (ObjectUtil.isNotEmpty(secondInterServerRes)) {
            // 不为空则继续获取下级
            List<JSONObject> secondServersDataList = JSONObject.parseArray(secondInterServerRes.toJSONString(), JSONObject.class);
            for (JSONObject secondServersData : secondServersDataList) {
                // 上级存在则直接放入对应数据中，避免缺少上级数据
                if (ObjectUtil.isNotEmpty(parentServerData)) {
                    serverData.put("parent", handleParentServerData(parentServerData));
                }
                recursionServersDataList(serverData, secondServersData, goodsServerIdList, handleServersDataList);
            }
        } else {
            String ydServeId = serverData.getString("YdServeId");
            // 只会获取已经匹配的区服，未匹配的不会操作
            if (StringUtils.isNotEmpty(ydServeId)) {
                List<String> ydServeIdList = Arrays.asList(ydServeId.split(", "));
                // 匹配的虞都区服列表与商品对应的区服列表做对比，只要两个 list 中有一个相同的就会进行处理
                if (ydServeIdList.stream().anyMatch(goodsServerIdList::contains)) {
                    String allServerId = "";
                    // 如果不存在上级数据，则不会进行处理
                    if (ObjectUtil.isNotEmpty(parentServerData)) {
                        serverData.put("parent", handleParentServerData(parentServerData));
                        // 父级中包含完整的区服 id，所以此处先放入上级数据，再从上级数据中获取完整区服 id
                        allServerId += ", " + serverData.getJSONObject("parent").getString("allServerId");
                    }
                    // 将底层区服 id 拼接，获取真正完整的区服 id
                    allServerId += ", " + serverData.getString("YdServeId");
                    // 现将区服 id 转为 list，然后转为 set，作用是为了去重
                    List<String> allServerIdList = Arrays.asList(allServerId.substring(2).split(", "));
                    Set<String> allServerIdSet = new LinkedHashSet<>(allServerIdList);
                    // 放入完整的区服 id
                    serverData.put("allServerId", allServerIdSet);
                    // 放入处理之后的区服信息列表
                    handleServersDataList.add(serverData);
                }
            }
        }
    }

    /**
     * 处理上级区服数据
     *
     * @param parentServerData 上级区服数据
     * @return
     */
    private JSONObject handleParentServerData(JSONObject parentServerData) {
        JSONObject parentData = new JSONObject();
        // 放入上级基础数据
        parentData.put("YdServeName", parentServerData.getString("YdServeName"));
        parentData.put("YdServeId", parentServerData.getString("YdServeId"));
        parentData.put("name", parentServerData.getString("name"));
        parentData.put("InterServeId", parentServerData.getString("InterServeId"));
        parentData.put("InterServeName", parentServerData.getString("InterServeName"));
        parentData.put("id", parentServerData.getString("id"));
        parentData.put("uuid", parentServerData.getString("uuid"));
        // 获取上级匹配区服数据
        JSONObject parentServerJson = parentServerData.getJSONObject("parent");
        if (ObjectUtil.isNotEmpty(parentServerJson)) {
            // 此处添加上级数据
            parentData.put("parent", parentServerData.getJSONObject("parent"));
        }
        // 获取完整的区服 id
        String allServerId = ObjectUtil.isEmpty(parentServerJson) ? "" : parentServerJson.getString("allServerId");
        if (ObjectUtil.isEmpty(allServerId)) {
            allServerId = ", " + parentServerData.getString("YdServeId");
        } else {
            allServerId += ", " + parentServerData.getString("YdServeId");
        }
        if (allServerId.startsWith(", "))
            allServerId = allServerId.substring(2);
        parentData.put("allServerId", allServerId);
        return parentData;
    }

    /**
     * 匹配商品区服信息与匹配的区服列表进行比较，看有多个数据完成匹配
     *
     * @param goodsServerIdList 商品区服列表
     * @param ydServerIdList    匹配的区服列表
     * @return 商品区服列表与匹配的区服列表两个列表匹配的个数
     */
    private int listMatchCount(List<String> goodsServerIdList, LinkedHashSet<String> ydServerIdList) {
        int count = 0;
        for (String element : ydServerIdList) {
            if (goodsServerIdList.contains(element)) {
                count++;
            }
        }
        return count;
    }

    //==========================================================单选匹配==========================================================//

    /**
     * 游戏单选信息匹配
     *
     * @param goodsInfoAndAttrValueDto 商品信息
     * @param interAttrRadio           需要匹配的所有单选信息
     */
    public JSONObject matchGoodsRadioAttr(GoodsInfoAndAttrValueDto goodsInfoAndAttrValueDto, String interAttrRadio) {
        return builderAttr(goodsInfoAndAttrValueDto, interAttrRadio, "radio");
    }

    //==========================================================多选匹配==========================================================//

    /**
     * 游戏单选信息匹配
     *
     * @param goodsInfoAndAttrValueDto 商品信息
     * @param interAttrCheckbox        需要匹配的所有多选信息
     */
    public JSONObject matchGoodsCheckboxAttr(GoodsInfoAndAttrValueDto goodsInfoAndAttrValueDto, String interAttrCheckbox) {
        return builderAttr(goodsInfoAndAttrValueDto, interAttrCheckbox, "checkbox");
    }

    //==========================================================输入匹配==========================================================//

    /**
     * 游戏单选信息匹配
     *
     * @param goodsInfoAndAttrValueDto 商品信息
     * @param interAttrInput           需要匹配的所有输入信息
     */
    public JSONObject matchGoodsInputAttr(GoodsInfoAndAttrValueDto goodsInfoAndAttrValueDto, String interAttrInput) {
        return builderAttr(goodsInfoAndAttrValueDto, interAttrInput, "input");
    }

    //==========================================================匹配公用方法==========================================================//

    /**
     * 开始构建匹配属性
     *
     * @param goodsInfoAndAttrValueDto 商品信息
     * @param interAttr                需要匹配的属性
     * @param templateType             匹配模板类型
     */
    public JSONObject builderAttr(GoodsInfoAndAttrValueDto goodsInfoAndAttrValueDto, String interAttr, String templateType) {
        // 开始匹配属性
        JSONObject interAttrJson = JSONObject.parseObject(interAttr);
        // 对应属性名
        String interAttrFieldName = templateType.equals("radio") ? "interRadioReqs" : templateType.equals("checkbox") ? "interCheckBoxReqs" : templateType.equals("input") ? "inputJson" : "";
        // 获取游戏属性的子对象
        String interAttrStr = interAttrJson.getString(interAttrFieldName);
        // 单选属性的 list 列表
        List<JSONObject> jsonDataList = JSONObject.parseArray(interAttrStr, JSONObject.class);
        if (jsonDataList.size() == 0) throw new GlobalException("属性未匹配，请匹配后重试！");
        // 获取游戏属性模板
        List<GameAttrTemplate> gameAttrTemplates = getGameTemplate(goodsInfoAndAttrValueDto, templateType);
        //获取所有字段以及字段值
        Map<String, Object> declaredFieldsMap = getDeclaredFieldsMap(goodsInfoAndAttrValueDto);
        List<Map<String, String>> gameAttrTempAndValueList = new ArrayList<>();
        // 遍历模板并获取商品对应的属性
        for (GameAttrTemplate gameAttrTemplate : gameAttrTemplates) {
            // 获取匹配字段
            String aavName = gameAttrTemplate.getAavName();
            if (StringUtils.isNotEmpty(aavName)) {
                // 获取对应匹配字段值
                Object aavNameValue = declaredFieldsMap.get(aavName);
                if (ObjectUtil.isNotEmpty(aavNameValue)) {
                    // 游戏属性模板和对应字段值的 map
                    Map<String, String> gameAttrTempAndValueMap = new HashMap<>();
                    gameAttrTempAndValueMap.put("id", gameAttrTemplate.getId().toString());
                    gameAttrTempAndValueMap.put("value", aavNameValue.toString());
                    gameAttrTempAndValueMap.put("aavName", aavName);
                    gameAttrTempAndValueMap.put("fieldName", gameAttrTemplate.getFieldName());
                    gameAttrTempAndValueList.add(gameAttrTempAndValueMap);
                }
            }
        }
        // 匹配结果集
        List<JSONObject> matchResultList = new ArrayList<>();
        // 获取需要匹配以及默认的数据
        Map<String, List<JSONObject>> dataMap = getMatchDataAndDefaultData(jsonDataList, templateType);
        // 处理属性进行匹配，并返回默认匹配数据
        List<JSONObject> defaultMatchList = handleProperties(dataMap, gameAttrTempAndValueList, templateType, matchResultList);
        JSONObject resultJson = new JSONObject();
        resultJson.put("match", matchResultList);
        resultJson.put("default", defaultMatchList);
        return resultJson;
    }

    /**
     * 获取游戏选项模板属性
     *
     * @param goodsInfoAndAttrValueDto 商品信息
     * @param templateType             模板类型
     * @return 游戏选项模板属性
     */
    private List<GameAttrTemplate> getGameTemplate(GoodsInfoAndAttrValueDto goodsInfoAndAttrValueDto, String templateType) {
        GameAttrTemplate gameAttrTemplate = new GameAttrTemplate();
        gameAttrTemplate.setGameId(goodsInfoAndAttrValueDto.getGameId());
        gameAttrTemplate.setIsEnable("0");
        if (StringUtils.equals(templateType, "radio")) {
            gameAttrTemplate.setFieldType("radio");
        } else if (StringUtils.equals(templateType, "checkbox")) {
            List<String> types = new ArrayList<>();
            types.add("checkbox");
            types.add("boxradio");
            gameAttrTemplate.setFieldTypes(types);
        } else if (StringUtils.equals(templateType, "input")) {
            ArrayList types = new ArrayList<>();
            types.add("number");
            types.add("input");
            gameAttrTemplate.setFieldTypes(types);
        } else {
            throw new GlobalException("模板类型错误");
        }
        // 通过指定条件获取所有游戏选项模板属性
        return gameAttrTemplateMapper.selectGameAttrTemplateList(gameAttrTemplate);
    }

    /**
     * 获取对象对应的字段以及值
     *
     * @param goodsInfoAndAttrValueDto 商品信息
     * @return 对象对应的字段以及值
     */
    private Map<String, Object> getDeclaredFieldsMap(GoodsInfoAndAttrValueDto goodsInfoAndAttrValueDto) {
        Map<String, Object> resultMap = new HashMap<>();
        //通过反射获取所有字段
        Field[] declaredFields = goodsInfoAndAttrValueDto.getClass().getDeclaredFields();
        for (Field field : declaredFields) {
            field.setAccessible(true);
            try {
                Object o = field.get(goodsInfoAndAttrValueDto);
                if (ObjectUtil.isNotEmpty(o))
                    resultMap.put(field.getName(), field.get(goodsInfoAndAttrValueDto));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return resultMap;
    }

    /**
     * 获取需要匹配以及默认的数据
     *
     * @param jsonDataList 根据类型拿到的所有匹配数据
     * @param templateType 数据匹配模版类型
     * @return
     */
    private Map<String, List<JSONObject>> getMatchDataAndDefaultData(List<JSONObject> jsonDataList, String templateType) {
        // 分好类的数据（需要匹配以及默认的）
        Map<String, List<JSONObject>> dataMap = new HashMap<>();
        // 需要匹配的数据列表
        List<JSONObject> matchDataList = new ArrayList<>();
        // 需要默认的数据列表
        List<JSONObject> defaultDataList = new ArrayList<>();
        // 遍历数据
        for (JSONObject object : jsonDataList) {
            // 需要匹配的字段值，存在则说明需要进行匹配；如果是输入选项则需要通过 f1....等字段进行对应，所以获取 aavName 对应的值
            String matchFieldValue = templateType.equals("input") ? object.getString("aavName") : object.getString("YdConfigId");
            // 存在默认值则说明需要进行默认匹配，所有选项都以此字段做匹配
            String defaultValue = object.getString("defaultValue");
            // 同时存在匹配和默认属性，则进行匹配数据
            if (StringUtils.isNotEmpty(matchFieldValue)) {
                matchDataList.add(object);
            } else if (StringUtils.isNotEmpty(defaultValue)) {
                // 处理默认匹配数据
                JSONObject defaultMatchData = handleDefaultMatchData(object, templateType);
                if (ObjectUtil.isNotEmpty(defaultMatchData))
                    object.put("matchData", defaultMatchData);
                if (templateType.equals("radio")) {
                    removeInterAttrByKey("interRadioReqs,interServerRes", object);
                } else if (templateType.equals("checkbox")) {
                    removeInterAttrByKey("interCheckBoxReqs,interServerRes", object);
                }
                defaultDataList.add(object);
            }
        }
        // 将结果放入对应字段，方便后续操作
        dataMap.put("match", matchDataList);
        dataMap.put("default", defaultDataList);
        return dataMap;
    }

    /**
     * 处理默认匹配数据
     *
     * @param defaultMatchData 默认匹配数据
     * @param templateType     匹配模板类型
     * @return 默认匹配到的数据
     */
    private JSONObject handleDefaultMatchData(JSONObject defaultMatchData, String templateType) {
        String defaultMatchChild = "";
        if (templateType.equals("radio")) {
            defaultMatchChild = defaultMatchData.getString("interRadioReqs");
        } else if (templateType.equals("checkbox")) {
            defaultMatchChild = defaultMatchData.getString("interCheckBoxReqs");
        }
        if (StringUtils.isNotEmpty(defaultMatchChild)) {
            List<JSONObject> defaultMatchChildList = JSONObject.parseArray(defaultMatchChild, JSONObject.class);
            for (JSONObject defaultChild : defaultMatchChildList) {
                if (StringUtils.isNotEmpty(defaultChild.getString("defaultValue"))) {
                    return defaultChild;
                }
            }
        }
        return null;
    }

    /**
     * 处理属性匹配
     *
     * @param dataMap                  数据集
     * @param gameAttrTempAndValueList 游戏属性模板列表
     * @param templateType             模板类型
     * @param matchResultList          匹配结果集
     * @return 需要默认匹配的结果集
     */
    private List<JSONObject> handleProperties(Map<String, List<JSONObject>> dataMap, List<Map<String, String>> gameAttrTempAndValueList, String templateType, List<JSONObject> matchResultList) {
        // 获取需要匹配的数据
        List<JSONObject> matchDataList = dataMap.get("match");
        // 遍历匹配模板
        int gameAttrTempSize = gameAttrTempAndValueList.size();

        // 遍历匹配数据
        for (JSONObject dataJson : matchDataList) {
            // 获取匹配数据匹配字段的值，如果是输入选项则需要通过 f1....等字段进行对应，所以获取 aavName 对应的值（前面分类时已经判断过了，所以这里的 matchFieldValue 不可能为空）
            String matchFieldValue = templateType.equals("input") ? dataJson.getString("aavName") : dataJson.getString("YdConfigId");
            // 将匹配数据对应的匹配值转为 list
            List<String> matchFieldValueList = Arrays.asList(matchFieldValue.split(", "));
            // 匹配数据只要匹配成功一次就不在进入
            boolean isFirstMatch = false;
            // 各个数据匹配的单个结果集
            List<JSONObject> matchCheckboxDataList = new ArrayList<>();
            for (int i = 0; i < gameAttrTempSize; i++) {
                // 匹配数据匹配最后一个模板
                boolean gameAttrTempLastMatch = false;
                if (i == gameAttrTempSize - 1) gameAttrTempLastMatch = true;
                // 获取当前模板
                Map<String, String> gameAttrTemp = gameAttrTempAndValueList.get(i);
                // 获取匹配模板的对应值，输入选项则需要通过 f1....等字段进行对应，所以获取 aavName 对应的值
                String gameAttrTempValue = templateType.equals("input") ? gameAttrTemp.get("aavName") : gameAttrTemp.get("id");
                // 如果匹配数据对应的值，包含匹配模板的对应值，则进行数据匹配（输入选项除外，输入选项只要匹配成功则就会处理结果，结果不存在则直接赋值 0）
                boolean isContains = matchFieldValueList.contains(gameAttrTempValue);
                // 如果匹配了，说明此匹配数据有对应匹配，不在给定匹配值
                if (isContains && !isFirstMatch) isFirstMatch = true;
                // 如果为匹配数据，且没有对应匹配值，则给定默认值，并匹配默认数据
                if (gameAttrTempLastMatch && !isFirstMatch) {
                    gameAttrTemp.put("value", "default");
                    gameAttrTemp.put("fieldName", dataJson.getString("YdConfigName"));
                    isContains = true;
                }
                if (isContains) {
                    // 获取模板中当前商品 aavName 字段所对应的值
                    String aavNameValue = gameAttrTemp.get("value");
                    try {
                        boolean isMatch = false;
                        // 根据类型进行数据匹配
                        if (templateType.equals("radio"))
                            // 单选匹配
                            isMatch = matchRadioProperties(dataJson, aavNameValue, matchResultList);
                        else if (templateType.equals("checkbox")) {
                            // 多选匹配
                            matchCheckboxProperties(dataJson, aavNameValue, matchCheckboxDataList);
                        } else if (templateType.equals("input"))
                            // 输入匹配
                            isMatch = matchInputProperties(dataJson, aavNameValue, matchResultList);
                        else throw new GlobalException("无效模板参数");
                        if (isMatch) break;
                    } catch (Exception e) {
                        String matchTypeName = templateType.equals("radio") ? "单选项" : templateType.equals("checkbox") ? "多选项" : templateType.equals("input") ? "输入项" : "";
                        throw new GlobalException(matchTypeName + gameAttrTemp.get("fieldName") + "匹配错误!\n" + e.getMessage());
                    }
                }
                // 如果是多选，且最后一次匹配，则将结果放入匹配数据中
                if (templateType.equals("checkbox") && gameAttrTempLastMatch && ObjectUtil.isNotEmpty(matchCheckboxDataList)) {
                    // 避免无限套娃，以及影响下次循环
                    JSONObject cloneJsonData = dataJson.clone();
                    removeInterAttrByKey("interCheckBoxReqs,interServerRes", cloneJsonData);
                    cloneJsonData.put("matchData", matchCheckboxDataList);
                    matchResultList.add(cloneJsonData);
                }
            }
        }
        // 获取默认匹配的数据
        return dataMap.get("default");
    }

    /**
     * 单选属性的匹配
     *
     * @param interAttrJson        顶级匹配数据
     * @param aavNameValue         匹配字段对应的值
     * @param radioMatchResultList 单选项匹配结果集
     * @return 此属性是否匹配成功
     */
    private boolean matchRadioProperties(JSONObject interAttrJson, String aavNameValue, List<JSONObject> radioMatchResultList) {
        // 匹配的下级数据
        List<JSONObject> interChildrenJson = JSONObject.parseArray(interAttrJson.getString("interRadioReqs"), JSONObject.class);
        // 通过流处理，获取需要匹配的 json 数据
        List<JSONObject> matchChildrenJson = new ArrayList<>();
        if (!aavNameValue.equals("default")) {
            for (JSONObject childrenJson : interChildrenJson) {
                String ydConfigId = childrenJson.getString("YdConfigId");
                if (ObjectUtil.isNotEmpty(ydConfigId)) {
                    if (ydConfigId.contains(aavNameValue))
                        matchChildrenJson.add(childrenJson);
                }
            }
        } else {
            // 如何为匹配数据且没有匹配值，则获取第一个
            matchChildrenJson.add(interChildrenJson.get(0));
        }

        // 获取参数是否为必填
        Boolean required = interAttrJson.getBoolean("required");
        if (ObjectUtil.isEmpty(required)) {
            required = false;
        }
        // 获取匹配数据默认值
        String defaultValue = interAttrJson.getString("defaultValue");
        // 匹配数据为空，属性为必填，默认值不为空则进行数据匹配
        if (ObjectUtil.isEmpty(matchChildrenJson) && required) {
            if (StringUtils.isNotEmpty(defaultValue)) {
                // 避免无限套娃，以及影响下次循环
                JSONObject cloneJsonData = interAttrJson.clone();
                removeInterAttrByKey("interRadioReqs,interServerRes", cloneJsonData);
                cloneJsonData.put("matchData", cloneJsonData.clone());
                radioMatchResultList.add(interAttrJson);
                return true;
            } else {
                throw new GlobalException("属性" + interAttrJson.getString("InterConfigName") + " 接口要求必传，但是暂未匹配到，请设置默认值");
            }
        }
        if (ObjectUtil.isNotEmpty(matchChildrenJson)) {
            // 避免无限套娃，以及影响下次循环
            JSONObject cloneJsonData = interAttrJson.clone();
            removeInterAttrByKey("interRadioReqs,interServerRes", cloneJsonData);
            cloneJsonData.put("matchData", matchChildrenJson.get(0));
            radioMatchResultList.add(cloneJsonData);
            return true;
        }
        return false;
    }

    /**
     * 多选属性的匹配
     *
     * @param interAttrJson           顶级匹配数据
     * @param aavNameValue            匹配字段对应的值
     * @param checkboxMatchResultList 多选项匹配结果集
     */
    private void matchCheckboxProperties(JSONObject interAttrJson, String aavNameValue, List<JSONObject> checkboxMatchResultList) {
        // 下级数据
        List<JSONObject> interChildrenJson = JSONObject.parseArray(interAttrJson.getString("interCheckBoxReqs"), JSONObject.class);
        // 存储多选属性的 list 列表
        List<JSONObject> checkboxReqsList = new ArrayList<>();
        if (!aavNameValue.equals("default")) {
            // 遍历下级数据
            for (JSONObject childrenJson : interChildrenJson) {
                String[] aavNameValueArray = aavNameValue.split(",");
                String ydConfigId = childrenJson.getString("YdConfigId");
                if (StringUtils.isNotEmpty(ydConfigId)) {
                    for (String aavValue : aavNameValueArray) {
                        if (Objects.equals(aavValue, ydConfigId)) {
                            checkboxReqsList.add(childrenJson);
                        }
                    }
                }
            }
        } else {
            checkboxReqsList.add(interChildrenJson.get(0));
        }
        // 多选属性不为空，则进行结果处理
        if (StringUtils.isNotEmpty(checkboxReqsList)) {
            checkboxMatchResultList.addAll(checkboxReqsList);
        }
    }

    /**
     * 输入属性的匹配
     *
     * @param interAttrJson        顶级匹配数据
     * @param aavNameValue         匹配字段对应的值
     * @param inputMatchResultList 输入项项匹配结果集
     */
    private boolean matchInputProperties(JSONObject interAttrJson, String aavNameValue, List<JSONObject> inputMatchResultList) {
        Boolean required = interAttrJson.getBoolean("required");
        if (ObjectUtil.isEmpty(required)) {
            required = false;
        }
        if (required && StringUtils.isEmpty(aavNameValue)) {
            throw new GlobalException(interAttrJson.getString("fieldName") + "必传，但是该商品没有该值");
        }
        if (StringUtils.isNotEmpty(aavNameValue)) {
            // 将匹配到的数据和匹配值放入结果集
            interAttrJson.put("matchData", aavNameValue.equals("default") ? "0" : aavNameValue);
            inputMatchResultList.add(interAttrJson);
            return true;
        }
        return false;
    }

    /**
     * 移除对象中对应的元素
     *
     * @param keys          需要移除元素的key
     * @param interAttrData 匹配的数据
     */
    private void removeInterAttrByKey(String keys, JSONObject interAttrData) {
        if (StringUtils.isNotEmpty(keys)) {
            List<String> keyList = Arrays.asList(keys.split(","));
            interAttrData.keySet().removeAll(keyList);
        }
    }

    //==========================================================匹配公用方法结束==========================================================//

    //==========================================================处理匹配结果==========================================================//

    /**
     * 处理匹配结果
     *
     * @param matchResult           匹配的结果
     * @param resultKey,resultValue 参数的key 例如：params中存储的为 map 类型
     *                              注：resultKey 和 resultValue 必须是存在于 matchResult 中的 key
     *                              如果 key 需要拆分或 value 需要拆分
     *                              例如：smrz&实名认证，拆分格式为 InterConfigId,&,1
     *                              InterConfigId：json 数据中存在的 key
     *                              ,：固定写法
     *                              &：数据 key 中自定义的分隔符
     *                              1：需要拆分后的哪一个作为 key，不写则默认为 0
     * @return
     */
    public Map<String, Object> handlesMatchResult(JSONObject matchResult, String resultKey, String resultValue) {
        // 匹配数据
        List<JSONObject> matchJsonList = JSONObject.parseArray(matchResult.getString("match"), JSONObject.class);
        // 默认匹配数据
        List<JSONObject> defaultJsonList = JSONObject.parseArray(matchResult.getString("default"), JSONObject.class);
        // 处理结果的 map
        Map<String, Object> handlesResultMap = new TreeMap<>();
        //=============== 处理匹配结果 ===============//
        for (JSONObject matchJson : matchJsonList) {
            String matchMapKey = getMatchMapKeyValue(matchJson, resultKey);
            // 获取匹配数据
            Object matchData = matchJson.get("matchData");
            if (matchData instanceof JSONObject) {// 单选
                String matchMapValue = getMatchMapKeyValue((JSONObject) matchData, resultValue);
                handlesResultMap.put(matchMapKey, matchMapValue);
            } else if (matchData instanceof List) {// 多选
                List<String> checkboxMatchList = new ArrayList<>();
                for (JSONObject checkboxMatchData : (List<JSONObject>) matchData) {
                    String matchMapValue = getMatchMapKeyValue(checkboxMatchData, resultValue);
                    checkboxMatchList.add(matchMapValue);
                }
                handlesResultMap.put(matchMapKey, checkboxMatchList);
            } else if (matchData instanceof String) {//输入
                handlesResultMap.put(matchMapKey, matchData.toString());
            }
        }
        //=============== 处理默认匹配结果 ===============//
        for (JSONObject defaultJson : defaultJsonList) {
            Object defaultMatchData = defaultJson.get("matchData");
            if (defaultMatchData instanceof String) {
                String matchMapKey = defaultJson.getString("id");
                handlesResultMap.put(matchMapKey, "0");
            } else {
                String defaultMapKey = defaultJson.getString("defaultValue");
                String defaultMapValue = getMatchMapKeyValue((JSONObject) defaultMatchData, resultValue);
                handlesResultMap.put(defaultMapKey, defaultMapValue);
            }
        }
        return handlesResultMap;
    }

    private String getMatchMapKeyValue(JSONObject matchJson, String keyOrValue) {
        String[] resultKeySplit = keyOrValue.split(",");
        // 根据 json 字段获取 json 的对应值
        String matchMapKeyValue = matchJson.getString(resultKeySplit[0]);
        // 判断 json 的值是否存在分割
        if (resultKeySplit.length == 2) {
            matchMapKeyValue = matchMapKeyValue.split(resultKeySplit[1])[0];
        } else if (resultKeySplit.length == 3) {
            matchMapKeyValue = matchMapKeyValue.split(resultKeySplit[1])[Integer.parseInt(resultKeySplit[2])];
        } else {
            throw new GlobalException("填写的 " + keyOrValue + " 不符合标准！");
        }
        return matchMapKeyValue;
    }

    //==========================================================根据 url 将图片转为 File 文件==========================================================//

    /**
     * 通过url上传图片
     *
     * @param imgUrl
     * @return
     */
    public File uploadImgByImgUrl(String imgUrl) {
        String string = DigestUtils.md5Hex(imgUrl);
        File file = null;
        try {
            URL url = new URL(imgUrl);
            BufferedImage image = ImageIO.read(url.openStream());
            byte[] bytes = ImgUntil.bufferedImageToByteArray(image);
            long srcSize = bytes.length;
            if (srcSize / 1024 > 5000) {
                bytes = ImgUntilYS.compressPicForScale(bytes, 3072l);
            } else {
                bytes = ImgUntilYS.compressPicForScale(bytes, 2048l);
            }
            file = convert(bytes, string);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return file;
    }

    private File convert(byte[] byteArray, String s) throws IOException {
        File file = File.createTempFile(s.substring(0, 13), ".jpg");
        try (FileOutputStream fos = new FileOutputStream(file)) {
            fos.write(byteArray);
        } catch (Exception e) {

        }
        return file;
    }

    public static void main(String[] args) {

    }
}
